using System;
using System.Diagnostics;
using System.Xml;
using System.Xml.Serialization;
using Microsoft.SharePoint.WebPartPages;

namespace DE.Sdc.SharePoint.Common.Deployment
{
    [Serializable]
    [XmlType(AnonymousType = true, Namespace = "http://sdc/2009/07/Deployment/1.0/ContentStructure")]
    [XmlRoot(Namespace = "http://sdc/2009/07/Deployment/1.0/ContentStructure", IsNullable = false)]
    public class WebPart : NamedElement
    {
        /// <remarks/>
        [XmlAttribute]
        public string Zone { get; set; }

        /// <remarks/>
        [XmlAttribute]
        public int Order { get; set; }

        /// <remarks/>
        [XmlAttribute]
        public string ImportXml { get; set; }

        /// <summary>
        /// Adds, Replaces or Deletes, Modifies or Moves a webpart in a given webpart manager
        /// </summary>
        /// <param name="webPartDefinition">Xml object for a webpart</param>
        /// <param name="webPart">A webpart based on the webPartDefinition or null</param>
        /// <param name="webPartManager">The parent webPartManager where to insert the webpart</param>
        protected internal void ImportWebPart(WebPart webPartDefinition, System.Web.UI.WebControls.WebParts.WebPart webPart, SPLimitedWebPartManager webPartManager)
        {
            Trace.WriteLine("Try to import WebPart '" + webPartDefinition.Title + "' in '" + webPartDefinition.Zone + "'.", "ContentStructureImporter:ImportWebPart");

            if (webPart == null)
            {
                if (webPartDefinition.Action == ActionType.Add || webPartDefinition.Action == ActionType.Replace)
                    webPart = CreateWebPart(webPartDefinition, webPartManager);
                else
                    return;
            }
            else if (webPartDefinition.Action == ActionType.Replace)
            {
                webPartManager.DeleteWebPart(webPart);
                webPart = CreateWebPart(webPartDefinition, webPartManager);
            }
            else if (webPartDefinition.Action == ActionType.Delete)
            {
                webPartManager.DeleteWebPart(webPart);
                return;
            }

            if (webPart.IsClosed)
            {
                webPartManager.OpenWebPart(webPart);
                webPartManager.MoveWebPart(webPart, webPartDefinition.Zone, webPartDefinition.Order);
                webPartManager.SaveChanges(webPart);
            }

            Trace.WriteLine("WebPart '" + webPartDefinition.Title + "' in '" + webPartDefinition.Zone + "' imported.", "ContentStructureImporter:ImportWebPart");
        }

        /// <summary>
        /// Creates a webpart in a given webpart manager
        /// </summary>
        /// <param name="webPartDefinition">Xml object for a webpart</param>
        /// <param name="webPartManager">The webpart manager where to create the webpart</param>
        /// <returns></returns>
        private System.Web.UI.WebControls.WebParts.WebPart CreateWebPart(WebPart webPartDefinition, SPLimitedWebPartManager webPartManager)
        {
            Trace.WriteLine("Try to create WebPart '" + webPartDefinition.Title + "' in '" + webPartDefinition.Zone + "'.", "ContentStructureImporter:CreateWebPart");

            XmlTextReader xmlReader = null;

            try
            {
                string errorMessage;
                xmlReader = new XmlTextReader(GetFeatureRootedPath(webPartDefinition.ImportXml));
                System.Web.UI.WebControls.WebParts.WebPart webPart = webPartManager.ImportWebPart(xmlReader, out errorMessage);
                webPart.ID = webPartDefinition.Title ?? webPart.ID;
                webPartManager.AddWebPart(webPart, webPartDefinition.Zone, webPartDefinition.Order);

                return webPart;
            }
            catch (Exception ex)
            {
                throw new ContentStructureImporterException(
                    "Error while importing webpart file '" + webPartDefinition.ImportXml + "'", ex);
            }
            finally
            {
                if (xmlReader != null)
                    xmlReader.Close();

                Trace.WriteLine("WebPart '" + webPartDefinition.Title + "' in '" + webPartDefinition.Zone + "' created.", "ContentStructureImporter:ImportItem");
            }
        }
    }
}